package com.gylang.commons.util;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 对象赋值
 *
 * @author gylang
 * data 2020/7/4
 * @version v0.0.1
 */
public class PropertyUtils {


    /**
     * 通过setter方法赋值
     *
     * @param obj   赋值对象
     * @param key   赋值key
     * @param value 赋值val
     */
    public static void forceSetValue(Object obj, String key, Object value) {

        Class<?> aClass = obj.getClass();
        try {
            Field field = aClass.getDeclaredField(key);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 反射赋值通过setter方法赋值
     *
     * @param obj   赋值对象
     * @param key   赋值key
     * @param value 赋值val
     */
    public static void setValue(Object obj, String key, Object value) throws ReflectiveOperationException {
        invokeByMethodName(obj, setterName(key), value);
    }

    /**
     * 反射获取值
     *
     * @param obj getter方法对象
     * @param key 属性值
     * @return 对象值
     */
    public static Object getValue(Object obj, String key) throws ReflectiveOperationException {

        return invokeByMethodName(obj, getterName(key), null);
    }

    /**
     * 反射强制获取值
     *
     * @param obj getter方法对象
     * @param key 属性值
     * @return 对象值
     */
    public static Object forceGetValue(Object obj, String key) {
        Class<?> aClass = obj.getClass();
        try {
            Field field = aClass.getDeclaredField(key);
            field.setAccessible(true);
            return field.get(obj);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 反射将对象转成map
     *
     * @param source 待转读写
     * @return map
     */
    public static Map<String, Object> toMap(Object source) throws ReflectiveOperationException {

        Field[] fields = source.getClass().getDeclaredFields();
        Map<String, Object> property = new HashMap<>();
        for (Field field : fields) {
            Object value = getValue(source, field.getName());
            if (null != value) {

                property.put(field.getName(), value);

            }
        }

        return property;
    }

    /**
     * 反射调用方法setter 和 getter
     *
     * @param obj        调用对象
     * @param methodName 方法名
     * @param value      参数
     */
    private static Object invokeByMethodName(Object obj, String methodName, Object value) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

        if (StringUtils.isNotBlank(methodName)) {
            if (null == value) {
                Method method = obj.getClass().getMethod(methodName);
                return method.invoke(obj);
            } else {
                Method method = obj.getClass().getMethod(methodName, value.getClass());
                return method.invoke(obj, value);
            }

        }
        return null;
    }

    /**
     * 获取setter名字
     *
     * @param key 字段名
     * @return setter方法名
     */
    public static String setterName(String key) {

        return "set" + StringUtils.upperCase(key.charAt(0) + "") + key.substring(1);
    }

    /**
     * 获取setter名字
     *
     * @param key 字段名
     * @return setter方法名
     */
    public static String getterName(String key) {

        return "get" + StringUtils.upperCase(key.charAt(0) + "") + key.substring(1);
    }
}
